﻿using Abp.AutoMapper;
using Microsoft.EntityFrameworkCore;
using NetCore.Dtos;
using NetCore.Entities.Organizations;
using NetCore.Enums;
using NetCore.Interfaces;
using NetCore.LinqExtensions;
using NetCore.Organizations.Dtos;
using NetCore.Services;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;

namespace NetCore.Organizations
{
    /// <summary>
    /// 组织机构
    /// </summary>
    [Description("组织机构")]
    public class OrganizationAppService : BaseNetCoreAppService<Organization>, IOrganizationAppService
    {
        public OrganizationAppService(INetCoreRepository<Organization> baseRepository) : base(baseRepository)
        {
        }
        /// <summary>
        /// 获取所有组织机构
        /// </summary>
        /// <returns></returns>
        public async Task<IList<OrganizationDto>> Grid()
        {
            var result = await BaseRepository.GetAllListAsync();
            return result.MapTo<IList<OrganizationDto>>();
        }
        /// <summary>
        /// 获取所有叶子节点Id
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetLeafNodeIds()
        {
            var nodes = await BaseRepository.GetAll().Select(n => new { n.Id, n.ParentId }).ToListAsync();
            var leafNodeIds = nodes.Where(n => nodes.All(m => m.ParentId != n.Id)).Select(n => n.Id).Distinct().ToList();
            return leafNodeIds;
        }


        /// <summary>
        /// 获取所有父级节点Id
        /// </summary>
        /// <returns></returns>
        public async Task<List<int?>> GetParentNodeIds()
        {
            return await BaseRepository.GetAll().Where(m => m.ParentId.HasValue)
                .Select(n => n.ParentId)
                .Distinct().ToListAsync();
        }

        public async Task<List<Organization>> GetChildrens(List<Organization> parents)
        {
            var list = new List<Organization>();
            var items = parents.SelectMany(n => n.Children).ToList();
            var parentItems = items.Where(m => m.Children.Any()).ToList();
            if (parentItems.Any()) list.AddRange(await GetChildrens(parentItems));
            list.AddRange(items.Except(parentItems).ToList());
            return list;
        }

        public async Task<IEnumerable<OrganizationDto>> GetChildrenByItemIds(InputIdsDto input)
        {
            var parents = input.Ids.Any() ? BaseRepository.GetAll().Where(m => input.Ids.Contains(m.Id)).ToList() : new List<Organization>();
            var childrens = (await GetChildrens(parents)).MapTo<IEnumerable<OrganizationDto>>();
            //下面的功能也可，但不能将导航属性赋值给Dto
            //var list = ExpMapper<Organization, OrganizationDto>.Trans(childrens);
            return childrens;
        }

        public async Task<IEnumerable<OrganizationDto>> GetChildrenByItemId(InputIdDto input)
        {
            var parents = Get(m => m.Id == input.Id).ToList();
            var childrens = (await GetChildrens(parents)).MapTo<IEnumerable<OrganizationDto>>();
            //下面的功能也可，但不能将导航属性赋值给Dto
            //var list = ExpMapper<Organization, OrganizationDto>.Trans(childrens);
            return childrens;
        }

        public async Task<List<OrganizationDto>> GetAllChildren(InputIdDto input)
        {
            var childrens = new List<OrganizationDto>();
            var items = await Get(m => m.Id == input.Id).SelectMany(n => n.Children).ToListAsync();
            items.ForEach(async m =>
            {
                childrens.AddRange(await GetAllChildren(new InputIdDto { Id = m.Id }));
            });
            childrens.AddRange(items.MapTo<List<OrganizationDto>>());
            return childrens;
        }

        public async Task<List<OrganizationDto>> GetAllChildrenByItemIds(InputIdsDto input)
        {
            var items = await Get(m => input.Ids.Contains(m.Id)).SelectMany(n => n.Children).ToListAsync();
            var childrens = items.MapTo<List<OrganizationDto>>();
            childrens.AddRange(await GetAllChildrenByItemIds(new InputIdsDto { Ids = items.Select(m => m.Id).ToList() }));
            return childrens;
        }

        public async Task<List<Organization>> GetBrothersByParentId(InputIdDto input)
        {
            var brothers = await Get(m => m.ParentId == input.Id).ToListAsync();
            return brothers;
        }


        /// <summary>
        /// 给定根节点下TreeView数据源方法
        /// </summary>
        /// <param name="items">集合</param>
        /// <param name="selectedIds">选中项</param>
        /// <param name="disabled">是否禁用</param>
        /// <returns>TreeDtos</returns>
        private List<TreeDto> GetItemTree(List<Organization> items, List<int> selectedIds, bool disabled = false)
        {
            List<TreeDto> list = new List<TreeDto>();
            items.ForEach(item =>
            {
                list.Add(GetTreeDto(item, selectedIds, disabled));
                if (item.Children.Any())
                {
                    list.AddRange(GetItemTree(item.Children.ToList(), selectedIds, disabled));
                }
            });
            return list;
        }
        /// <summary>
        /// 单个节点设置
        /// </summary>
        /// <param name="item">节点</param>
        /// <param name="selectedIds">选中项</param>
        /// <param name="disabled">是否禁用</param>
        /// <returns>TreeDto</returns>
        private TreeDto GetTreeDto(Organization item, List<int> selectedIds, bool disabled = false)
        {
            return new TreeDto
            {
                Name = item.Name,
                ShowSelectBox = true,
                Disabled = disabled,
                Selected = selectedIds.Contains(item.Id),
                Key = item.Id.ToString(),
                //Remark = costItem.Remark,
                //TypeIcon = "list-alt",
                Id = item.Id,
                DbId = item.Id,
                ParentId = item.ParentId
            };
        }

        public async Task<List<Organization>> GetAllParentsByParentId(InputIdDto input)
        {
            var list = new List<Organization>();
            var parent = await BaseRepository.GetAll().GetAsync(input.Id);
            if (parent != null)
            {
                list.Add(parent);
                list.AddRange(await GetAllParentsByParentId(new InputIdDto { Id = parent.ParentId ?? 0 }));
            }
            return list;
        }

        public async Task<List<TreeDto>> GetRootItemTree(InputIdsDto input)
        {
            var roots = await Get(m => m.Level == TreeNodeLevel.根级).ToListAsync();
            var list = new List<TreeDto>();
            roots.ForEach(costItem =>
            {
                list.Add(GetTreeDto(costItem, input.Ids));
                //不需要展示子级
                //if (costItem.Childrens.Any())
                //{
                //    list.AddRange(GetItemTree(costItem.Childrens.ToList(), selectedIds, true));
                //}
            });
            return list;
        }

        public async Task<List<TreeDto>> GetRootTrees(InputIdsDto input)
        {
            var roots = await Get(m => m.Level == TreeNodeLevel.根级).ToListAsync();
            var list = GetItemTree(roots, input.Ids);
            return list;
        }

        public void UpdateChildrenLevels(IQueryable<Organization> parents)
        {
            var items = parents.SelectMany(n => n.Children);
            items.Include(l => l.Parent).ToList().ForEach(m =>
            {
                m.Level = m.Parent?.Level + 1 ?? 0;
            });
            if (items.Any())
            {
                UpdateChildrenLevels(items);
            }
        }

        public async Task<IQueryable<SelectBox>> GetParentSelectList()
        {
            var parentIds = await GetParentNodeIds();
            return Get(m => parentIds.Contains(m.Id))
                .Select(m => new SelectBox
                {
                    Text = m.Name,
                    Value = m.Id
                });
        }


    }
}
